package com.xxkk.net.websocketNetty;

/**
 * @author xxkk
 * @version 1.0.0
 * @title Player
 * @description ʕ•ᴥ•ʔ
 * @create 2023/11/11 14:36
 **/

import com.ebo.synframework.nettybase.codec.ProtoEncoder;
import com.ebo.synframework.synroom.executor.SynRoomPlayer;
import com.google.protobuf.Message;
import com.xxkk.gameCore.enums.PlayerState;
import org.apache.log4j.Logger;
import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.http.websocketx.BinaryWebSocketFrame;

import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;

public class Player extends SynRoomPlayer {
    private final static Logger logger = Logger.getLogger(Player.class);
    private String loginIp;// 玩家登陆远程ip
    private Channel nettyChannel;
    private long roleId;
    private String platformId;// 玩家平台id
    private int areaId;// 玩家当前在线所在区
    private PlayerState playerState = PlayerState.offLine;// 登陆成功后设置玩家状态为在线
    private long connectionTime = System.currentTimeMillis();//玩家连接创建时间
    private long lastReqTime = System.currentTimeMillis();//最后一次发起请求活跃时间，用来判断用户是否掉线

    private ReentrantLock lock = new ReentrantLock();// 显示锁
    private Condition condition = lock.newCondition();// 控制显示锁状态
    private static ProtoEncoder protoEncoder = new ProtoEncoder();// 编码器
    private Map<String, Message> respMap = new ConcurrentHashMap<>();

    public void respond(String serviceAndMethod, Object builder) {
        this.respond(serviceAndMethod, builder, 0);
    }

    public void respond(String serviceAndMethod, Object builder, int cmdIndex) { //向客户端发送消息
        // websocket
        ChannelBuffer buffer = protoEncoder.encode0(serviceAndMethod, 2, builder,
                "", null, true, cmdIndex);
        if (buffer.readableBytes() < 8)
            logger.error("webSocket 传输消息内容过短，不在协议范围#方法：" + serviceAndMethod);
        BinaryWebSocketFrame webSocketFrame = new BinaryWebSocketFrame(buffer);
        if (this.nettyChannel.isOpen())
            this.nettyChannel.write(webSocketFrame);
        else
            logger.error("websocket通道关闭 发送消息失败：" + serviceAndMethod);
    }


    public void setRespAndNotify(String serviceAndMethod, Message message) {// 等待响应
        lock.lock();
        try {
            this.respMap.put(serviceAndMethod, message);
            this.condition.signalAll();
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            lock.unlock();
        }
    }

    public Message sendAndWaitResp(String serviceAndMethod, Object builder) {// 发送消息并等待返回
        lock.lock();
        Message resp = null;
        boolean waitFlag = false;
        try {
            this.respond(serviceAndMethod, builder);
            waitFlag = this.condition.await(5, TimeUnit.SECONDS);// wait for me 5s >_<
            if (waitFlag)
                resp = this.respMap.get(serviceAndMethod);
        } catch (Exception e) {
            logger.error(e.getMessage());
        } finally {
            lock.unlock();
        }
        this.respMap.remove(serviceAndMethod);
        if (!waitFlag)
            throw new RuntimeException(serviceAndMethod + "方法等待超时");
        return resp;
    }

    public Player() {
        super(-10000, null);
        this.nettyChannel = null;
        this.playerId = -1;
    }

    public Player(ChannelHandlerContext ctx) {
        super(ctx.getChannel().getId(), ctx);
        this.nettyChannel = ctx.getChannel();
    }

    public long getRoleId() {
        return this.roleId;
    }

    public void setRoleId(long roleId) {
        this.roleId = roleId;
    }

    public void setLastReqTime(long lastReqTime) {
        this.lastReqTime = lastReqTime;
    }

    // 掉线
    public void close() {
        this.nettyChannel.close();
    }

    public long getConnectionTime() { // TODO 待写定时任务刷掉一直连接却没有登陆的玩家
        return this.connectionTime;
    }

    public void setConnectionTime(long connectionTime) {
        this.connectionTime = connectionTime;
    }

    public Message getResp(String serviceAndMethod) {
        return respMap.get(serviceAndMethod);
    }

    public String getLoginIp() {
        return loginIp;
    }

    public void setLoginIp(String loginIp) {
        this.loginIp = loginIp;
    }

    public String getPlatformId() {
        return platformId;
    }

    public void setPlatformId(String platformId) {
        this.platformId = platformId;
    }

    public int getAreaId() {
        return areaId;
    }

    public void setAreaId(int areaId) {
        this.areaId = areaId;
    }

    public PlayerState getPlayerState() {
        return playerState;
    }

    public void setPlayerState(PlayerState playerState) {
        this.playerState = playerState;
    }
}